home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / progutil / stdwin.zoo / test / faced.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-19  |  6.9 KB  |  439 lines

  1. /* Simple bitmap editor.
  2.    Uses ".face" file format (48x48).
  3.    
  4.    TO DO:
  5.        - fix row/col confusion
  6.     - connect dots given by mouse move?
  7.     - optimize drawing of consequtive black squares
  8.     - add open... command
  9.     - add flexible input format
  10.     - support X bitmap format
  11.     */
  12.  
  13. #include <stdio.h>
  14. #include "stdwin.h"
  15.  
  16. #define ROWS 48
  17. #define COLS 48
  18. #define SIZE (ROWS < COLS ? ROWS : COLS)
  19.  
  20. #define BITS 16 /* Bits per word */
  21.  
  22. char bit[ROWS][COLS];
  23.  
  24. int xscale= 5;
  25. int yscale= 5;
  26.  
  27. WINDOW *win;
  28.  
  29. int changed= 0;
  30.  
  31.  
  32. main(argc, argv)
  33.     int argc;
  34.     char **argv;
  35. {
  36.     FILE *fp;
  37.     
  38.     winitnew(&argc, &argv);
  39.     
  40.     if (argc > 1) {
  41.         fp= fopen(argv[1], "r");
  42.         if (fp == NULL) {
  43.             wdone();
  44.             perror(argv[1]);
  45.             exit(1);
  46.         }
  47.         input(fp);
  48.         fclose(fp);
  49.     }
  50.     
  51.     setup();
  52.     
  53.  
  54.     for (;;) {
  55.         editing();
  56.         
  57.         if (changed) {
  58.             switch (waskync("Save changes?", 1)) {
  59.             case 1:
  60.                 if (!save(argc > 1 ? argv[1] : NULL))
  61.                     continue;
  62.                 break;
  63.             case -1:
  64.                 continue;
  65.             }
  66.         }
  67.         break; /* Out of loop */
  68.     }
  69.     
  70.     wdone();
  71.     exit(0);
  72. }
  73.  
  74. save(name)
  75.     char *name;
  76. {
  77.     FILE *fp;
  78.     char namebuf[256];
  79.     
  80.     namebuf[0]= '\0';
  81.     if (name == NULL) {
  82.         if (!waskfile("Save as", namebuf, (int)(sizeof namebuf), 1))
  83.             return 0;
  84.         name= namebuf;
  85.     }
  86.     fp= fopen(name, "w");
  87.     if (fp == NULL) {
  88.         wperror(name);
  89.         return 0;
  90.     }
  91.     output(fp);
  92.     fclose(fp);
  93.     return 1;
  94. }
  95.  
  96. #define MAIN_MENU    1
  97.  
  98. #define QUIT_ITEM    0
  99.  
  100. #define OP_MENU        2
  101.  
  102. #define CLEAR_ITEM    0
  103. #define SET_ITEM    1
  104. #define INVERT_ITEM    2
  105. #define TRANS_MAJ_ITEM    3
  106. #define TRANS_MIN_ITEM    4
  107. #define ROT_LEFT_ITEM    5
  108. #define ROT_RIGHT_ITEM    6
  109. #define FLIP_HOR_ITEM    7
  110. #define FLIP_VERT_ITEM    8
  111.  
  112. #define NOPS        9
  113.  
  114. extern int (*oplist[])(); /* Forward */
  115. void drawproc(); /* Forward */
  116.  
  117. int text_only;
  118.  
  119. setup()
  120. {
  121.     MENU *mp;
  122.     int width, height;
  123.     
  124.     if (wlineheight() == 1)
  125.         text_only= xscale= yscale= 1;
  126.     
  127.     wsetdefwinsize(COLS*xscale, ROWS*yscale);
  128.     
  129.     mp= wmenucreate(MAIN_MENU, "Faced");
  130.     wmenuadditem(mp, "Quit", 'Q');
  131.     mp= wmenucreate(OP_MENU, "Operations");
  132.     wmenuadditem(mp, "Clear all", -1);
  133.     wmenuadditem(mp, "Set all", -1);
  134.     wmenuadditem(mp, "Invert", -1);
  135.     wmenuadditem(mp, "Transpose major", -1);
  136.     wmenuadditem(mp, "Transpose minor", -1);
  137.     wmenuadditem(mp, "Rotate left", -1);
  138.     wmenuadditem(mp, "Rotate right", -1);
  139.     wmenuadditem(mp, "Flip horizontal", -1);
  140.     wmenuadditem(mp, "Flip vertical", -1);
  141.     
  142.     win= wopen("faced", drawproc);
  143.     if (win == NULL) {
  144.         wmessage("Can't open window");
  145.         return;
  146.     }
  147.     wsetdocsize(win, COLS*xscale, ROWS*yscale);
  148. }
  149.  
  150. editing()
  151. {
  152.     int value= 0;
  153.     
  154.     for (;;) {
  155.         EVENT e;
  156.         
  157.         wgetevent(&e);
  158.         switch (e.type) {
  159.         case WE_MOUSE_DOWN:
  160.             value= !getbit(e.u.where.h/xscale, e.u.where.v/yscale);
  161.         case WE_MOUSE_MOVE:
  162.         case WE_MOUSE_UP:
  163.             setbit(e.u.where.h/xscale, e.u.where.v/yscale, value);
  164.             break;
  165.         case WE_COMMAND:
  166.             switch (e.u.command) {
  167.             case WC_CLOSE:
  168.                 return;
  169.             case WC_CANCEL:
  170.                 changed= 0;
  171.                 return;
  172.             }
  173.         case WE_MENU:
  174.             switch (e.u.m.id) {
  175.             case MAIN_MENU:
  176.                 switch (e.u.m.item) {
  177.                 case QUIT_ITEM:
  178.                     return;
  179.                 }
  180.                 break;
  181.             case OP_MENU:
  182.                 if (e.u.m.item >= 0 && e.u.m.item < NOPS) {
  183.                     (*oplist[e.u.m.item])();
  184.                     wchange(win, 0, 0,
  185.                         COLS*xscale, ROWS*yscale);
  186.                     changed= 1;
  187.                 }
  188.                 break;
  189.             }
  190.         }
  191.     }
  192. }
  193.  
  194. int
  195. getbit(col, row)
  196. {
  197.     if (row >= 0 && row < ROWS && col >= 0 && col < COLS)
  198.         return bit[row][col];
  199.     else
  200.         return 0;
  201. }
  202.  
  203. setbit(col, row, value)
  204. {
  205.     if (row >= 0 && row < ROWS && col >= 0 && col < COLS &&
  206.             bit[row][col] != value) {
  207.         changed= 1;
  208.         bit[row][col]= value;
  209.         wchange(win, col*xscale, row*yscale,
  210.             (col+1)*xscale, (row+1)*yscale);
  211.     }
  212. }
  213.  
  214. void drawproc(win, left, top, right, bottom)
  215.     WINDOW *win;
  216. {
  217.     int row, col;
  218.     
  219.     if (left < 0)
  220.         left= 0;
  221.     if (right > COLS*xscale)
  222.         right= COLS*xscale;
  223.     if (top < 0)
  224.         top= 0;
  225.     if (bottom > ROWS*yscale)
  226.         bottom= ROWS*yscale;
  227.     
  228.     for (row= top/yscale; row*yscale < bottom; ++row) {
  229.         for (col= left/xscale; col*xscale < right; ++col) {
  230.             if (bit[row][col]) {
  231.                 if (text_only)
  232.                     wdrawchar(col, row, 'x');
  233.                 else
  234.                     wpaint(col*xscale, row*yscale,
  235.                         (col+1)*xscale, (row+1)*yscale);
  236.             }
  237.         }
  238.     }
  239. }
  240.  
  241.  
  242. /* File I/O routines */
  243.  
  244. input(fp)
  245.     FILE *fp;
  246. {
  247.     int row;
  248.     
  249.     for (row= 0; row < ROWS; ++row) {
  250.         read_row(fp, row);
  251.     }
  252. }
  253.  
  254. read_row(fp, row)
  255.     FILE *fp;
  256.     int row;
  257. {
  258.     int left= 0;
  259.     long ibuf;
  260.     int col;
  261.     
  262.     for (col= 0; col < COLS; ++col) {
  263.         if (left <= 0) {
  264.             if (fscanf(fp, " 0x%4lx,", &ibuf) != 1) {
  265.                 wdone();
  266.                 fprintf(stderr,
  267.                     "Bad input format, row %d\n", row);
  268.                 exit(1);
  269.             }
  270.             left= BITS;
  271.         }
  272.         --left;
  273.         bit[row][col]= (ibuf >> left) & 1;
  274.     }
  275. }
  276.  
  277. output(fp)
  278.     FILE *fp;
  279. {
  280.     int row;
  281.     
  282.     for (row= 0; row < ROWS; ++row)
  283.         write_row(fp, row);
  284. }
  285.  
  286. write_row(fp, row)
  287.     FILE *fp;
  288.     int row;
  289. {
  290.     int col;
  291.     int left= BITS;
  292.     long ibuf= 0;
  293.     
  294.     for (col= 0; col < COLS; ++col) {
  295.         if (left <= 0) {
  296.             fprintf(fp, "0x%04lX,", ibuf);
  297.             ibuf= 0;
  298.             left= BITS;
  299.         }
  300.         --left;
  301.         if (bit[row][col]) {
  302.             ibuf |= 1<<left;
  303.         }
  304.     }
  305.     if (left < BITS)
  306.         fprintf(fp, "0x%04lX,", ibuf);
  307.     fprintf(fp, "\n");
  308. }
  309.  
  310.  
  311. /* Data manipulation routines */
  312.  
  313. clear_bits()
  314. {
  315.     int row, col;
  316.     
  317.     for (row= 0; row < ROWS; ++row)
  318.         for (col= 0; col < COLS; ++col)
  319.             bit[row][col]= 0;
  320. }
  321.  
  322. set_bits()
  323. {
  324.     int row, col;
  325.     
  326.     for (row= 0; row < ROWS; ++row)
  327.         for (col= 0; col < COLS; ++col)
  328.             bit[row][col]= 1;
  329. }
  330.  
  331. invert_bits()
  332. {
  333.     int row, col;
  334.     
  335.     for (row= 0; row < ROWS; ++row)
  336.         for (col= 0; col < COLS; ++col)
  337.             bit[row][col]= !bit[row][col];
  338. }
  339.  
  340. transpose_major()
  341. {
  342.     int row, col;
  343.     char tmp;
  344.     
  345.     for (row= 0; row < SIZE; ++row) {
  346.         for (col= 0; col < row; ++col) {
  347.             tmp= bit[row][col];
  348.             bit[row][col]= bit[col][row];
  349.             bit[col][row]= tmp;
  350.         }
  351.     }
  352. }
  353.  
  354. transpose_minor()
  355. {
  356.     int row, col;
  357.     char tmp;
  358.     
  359.     for (row= 0; row < SIZE; ++row) {
  360.         for (col= 0; col < SIZE-1-row; ++col) {
  361.             tmp= bit[row][col];
  362.             bit[row][col]= bit[SIZE-1-col][SIZE-1-row];
  363.             bit[SIZE-1-col][SIZE-1-row]= tmp;
  364.         }
  365.     }
  366. }
  367.  
  368. rotate_left()
  369. {
  370.     int row, col;
  371.     char tmp;
  372.     
  373.     for (row= 0; row < SIZE/2; ++row) {
  374.         for (col= 0; col < SIZE/2; ++col) {
  375.             tmp= bit[row][col];
  376.             bit[row][col]= bit[col][SIZE-1-row];
  377.             bit[col][SIZE-1-row]= bit[SIZE-1-row][SIZE-1-col];
  378.             bit[SIZE-1-row][SIZE-1-col]= bit[SIZE-1-col][row];
  379.             bit[SIZE-1-col][row]= tmp;
  380.         }
  381.     }
  382. }
  383.  
  384. rotate_right()
  385. {
  386.     int row, col;
  387.     char tmp;
  388.     
  389.     for (row= 0; row < SIZE/2; ++row) {
  390.         for (col= 0; col < SIZE/2; ++col) {
  391.             tmp= bit[row][col];
  392.             bit[row][col]= bit[SIZE-1-col][row];
  393.             bit[SIZE-1-col][row]= bit[SIZE-1-row][SIZE-1-col];
  394.             bit[SIZE-1-row][SIZE-1-col]= bit[col][SIZE-1-row];
  395.             bit[col][SIZE-1-row]= tmp;
  396.         }
  397.     }
  398. }
  399.  
  400. flip_horizontal()
  401. {
  402.     int row, col;
  403.     char tmp;
  404.     
  405.     for (row= 0; row < ROWS; ++row) {
  406.         for (col= 0; col < COLS/2; ++col) {
  407.             tmp= bit[row][col];
  408.             bit[row][col]= bit[row][COLS-1-col];
  409.             bit[row][COLS-1-col]= tmp;
  410.         }
  411.     }
  412. }
  413.  
  414. flip_vertical()
  415. {
  416.     int row, col;
  417.     char tmp;
  418.     
  419.     for (row= 0; row < ROWS/2; ++row) {
  420.         for (col= 0; col < COLS; ++col) {
  421.             tmp= bit[row][col];
  422.             bit[row][col]= bit[ROWS-1-row][col];
  423.             bit[ROWS-1-row][col]= tmp;
  424.         }
  425.     }
  426. }
  427.  
  428. int (*oplist[])() = {
  429.     clear_bits,
  430.     set_bits,
  431.     invert_bits,
  432.     transpose_major,
  433.     transpose_minor,
  434.     rotate_left,
  435.     rotate_right,
  436.     flip_horizontal,
  437.     flip_vertical,
  438. };
  439.